import { HTTP_BASE_URL, ACCESS_TOKEN_KEY, REFRESH_TOKEN_KEY } from "@/config";

interface RquestConfig {
  url: string;
  method?: "GET" | "POST" | "PUT" | "DELETE";
  data?: any;
  options?: any;
}

interface RequestResult {
  code: 0 | 1 | 2;
  msg: string;
  data?: any;
}

interface RequestOption extends RquestConfig {
  header?: any;
}

// 请求队列和刷新状态
let isRefreshing = false;
let requestsQueue: any[] = [];

// 默认配置
const defaultConfig = {
  baseURL: HTTP_BASE_URL,
  timeout: 60000,
  refreshApi: "/refresh-token",
};

// Token过期处理
const handleTokenExpired = async (
  options: RequestOption,
  resolve: any,
  reject: any
) => {
  // 将请求加入队列
  if (isRefreshing) {
    return requestsQueue.push({ options, resolve, reject });
  }

  isRefreshing = true;

  try {
    // 执行Token刷新
    const access_token = await refreshToken();

    // 更新所有队列请求
    requestsQueue.forEach((item) => {
      item.options.header = {
        ...item.options.header,
        Authorization: `Bearer ${access_token}`,
      };
      request(item.options).then(item.resolve).catch(item.reject);
    });

    // 清空队列
    requestsQueue = [];

    // 重试当前请求
    options.header = {
      ...options.header,
      Authorization: `Bearer ${access_token}`,
    };
    request(options).then(resolve).catch(reject);
  } catch (error) {
    // 刷新失败处理
    uni.removeStorageSync(ACCESS_TOKEN_KEY);
    uni.removeStorageSync(REFRESH_TOKEN_KEY);
    // uni.reLaunch({ url: '/pages/login/login' });
    _customTip("认证信息已过期，请重新登录~", "/pages/login/login");
    reject(error);
  } finally {
    isRefreshing = false;
  }
};

// 刷新Token方法
const refreshToken = () => {
  return new Promise((resolve, reject) => {
    uni.request({
      url: defaultConfig.baseURL + defaultConfig.refreshApi,
      method: "POST",
      header: {
        "Content-Type": "application/json",
      },
      data: {
        refresh_token: uni.getStorageSync(REFRESH_TOKEN_KEY),
      },
      success: (res) => {
        const result: RequestResult = res.data as RequestResult;
        if (res.statusCode === 200 && result.code == 1) {
          uni.setStorageSync(ACCESS_TOKEN_KEY, result.data.access_token);
          uni.setStorageSync(REFRESH_TOKEN_KEY, result.data.refresh_token);
          resolve(result.data.access_token);
        } else {
          reject(new Error("刷新Token失败"));
        }
      },
      fail: (err) => reject(err),
    });
  });
};

// 基础请求方法
const request = (options: RequestOption) => {
  return new Promise((resolve, reject) => {
    uni.request({
      ...options,
      url: defaultConfig.baseURL + options.url,
      timeout: defaultConfig.timeout,
      header: {
        Authorization: `Bearer ${uni.getStorageSync(ACCESS_TOKEN_KEY)}`,
        ...options.header,
      },
      success: (res) => {
        const result: RequestResult = res.data as RequestResult;
        if (result.code === 2) {
          handleTokenExpired(options, resolve, reject);
        } else if (result.code !== 1) {
          _customTip(result.msg);
          reject(result);
        } else {
          resolve(res.data);
        }
      },
      fail: (err) => {
        _customTip(err.errMsg);
        reject(err);
      },
    });
  });
};

/**
 * msg 提升内容
 * path 跳转地址
 */
var isTipShowing = false;
const _customTip = (msg?: string, path?: string) => {
  // 防止多个toast
  if (isTipShowing) return;
  isTipShowing = true;
  uni.showModal({
    title: "系统提示",
    content: msg || "系统崩溃了，请稍后再试！",
    showCancel: false,
    success: (res) => {
      if (res.confirm && path) {
        uni.navigateTo({
          url: path,
        });
      }
    },
    complete: () => {
      setTimeout(() => {
        isTipShowing = false;
      }, 3000);
    },
  });
};

const http = (config: RquestConfig) => request(config);
// 创建实例
export default http;
